package com.ehotting.edsta.circuitDesign.gen;

import com.alibaba.fastjson.JSONObject;
import com.ehotting.edsta.circuitDesign.bean.AllMapBean;
import com.ehotting.edsta.circuitDesign.bean.CircuitElementBean;
import com.ehotting.edsta.circuitDesign.bean.CircuitGroupBean;
import com.ehotting.edsta.circuitDesign.bean.CircuitPackageBean;
import com.ehotting.edsta.circuitDesign.domain.EsCircuit;
import com.ehotting.edsta.circuitDesign.domain.EsCircuitType;
import com.ehotting.edsta.circuitDesign.domain.EsElement;
import com.ehotting.edsta.circuitDesign.enums.CircuitTypeEnum;
import com.ehotting.edsta.circuitDesign.enums.CodeDataTypeEnum;
import com.ehotting.edsta.circuitDesign.gen.circuit.CircuitScriptEngine;
import com.ehotting.edsta.circuitDesign.gen.element.ElementScriptEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CircuitEngine {

    private static final Logger logger = LoggerFactory.getLogger(CircuitEngine.class);

    @Autowired
    private CircuitScriptEngine circuitScriptEngine;
    @Autowired
    private ElementEngine elementEngine;
    @Autowired
    private CircuitGroupHelper circuitGroupHelper;



    public List<CircuitPackageBean> invoke(EsCircuitType circuitType, AllMapBean contextMap,String mainProjectId){

        logger.info("Start CircuitEngine.");
        Map<String,Object> context = contextMap.get(circuitType.getCircuitType(), CodeDataTypeEnum.INPUT_PARAM);
        List<EsCircuit> circuitList = circuitScriptEngine.invoke(circuitType.getId(),context,contextMap,mainProjectId);
        logger.info("circuitList.size():{}",circuitList.size());

        List<CircuitElementBean> circuitAndElementList = new ArrayList<>();
        String busCode = String.valueOf(contextMap.get("bus"));
        for(EsCircuit esCircuit : circuitList){
            CircuitElementBean circuitPackage = new CircuitElementBean(esCircuit);
            circuitPackage.setBus(String.valueOf(busCode));
            circuitAndElementList.add(circuitPackage);
        }

        //电路包组装，包括电路通道匹配
        List<CircuitGroupBean> circuitGroupList = circuitGroupHelper.convert( circuitType, circuitAndElementList, contextMap);
        logger.info("circuitGroupList.size():{}",circuitGroupList.size());

        //元器件计算
        elementEngine.invoke(circuitGroupList,context,contextMap);

        List<CircuitPackageBean> circuitPackageList = fillCircuitPackage(circuitGroupList);
        if (circuitType.getId() == 1 && circuitPackageList.size() > 0){
            circuitPackageList = circuitPackageList.stream().limit(5).collect(Collectors.toList());

        }
        logger.info("circuitPackageList.size():{}",circuitPackageList.size());

        logger.info("End CircuitEngine.");
        return circuitPackageList;
    }


    /**
     * 组合电路包
     * @param circuitGroupList
     * @return
     */
    private  List<CircuitPackageBean> fillCircuitPackage(List<CircuitGroupBean> circuitGroupList){
        if(circuitGroupList.size() == 0){
            return new ArrayList<>();
        }
        Map<String,List<CircuitGroupBean>> circuitGroupMapList = new HashMap<>();
        for(CircuitGroupBean circuitGroup : circuitGroupList){
            if(!circuitGroupMapList.containsKey(circuitGroup.getCircuitGroupKey())){
                circuitGroupMapList.put(circuitGroup.getCircuitGroupKey(),new ArrayList<>());
            }
            circuitGroupMapList.get(circuitGroup.getCircuitGroupKey()).add(circuitGroup);
        }
        Collection<List<CircuitGroupBean>> circuitGroupListList = circuitGroupMapList.values();
        List<CircuitPackageBean> circuitPackageList = cross(circuitGroupListList);
        /**
         * 限制电路包个数
         */
//        circuitPackageList = circuitPackageList.stream().limit(5).collect(Collectors.toList());
        return circuitPackageList;
    }



    /**
     * 将二维数据组转为一维数组
     * 比如[[a1,a2][b1,b2]]转换为[a1,b1][a1,b2][a2,b1][a2,b2]
     *
     * @param cgList
     * @return
     */
    private  List<CircuitPackageBean> cross(Collection<List<CircuitGroupBean>>  cgList) {
        List<CircuitPackageBean> newCgList = new ArrayList<>();
        newCgList.add(new CircuitPackageBean());
        for (List<CircuitGroupBean> ct : cgList) {
            newCgList = cross(newCgList, ct);
        }
        return newCgList;
    }

    /**
     * 使用*运算符来解包原始二维数组，使用嵌套循环来完成
     * 比如[[a1,a2][b1,b2]]转换为[a1,b1][a1,b2][a2,b1][a2,b2]
     *
     * @param cpList
     * @param cgList
     * @return
     */
    private static List<CircuitPackageBean> cross(
            List<CircuitPackageBean> cpList,
            List<CircuitGroupBean> cgList) {
        List<CircuitPackageBean> newCircuitGroupList = new ArrayList<>();
        for (CircuitPackageBean cp : cpList) {
            for (CircuitGroupBean cg : cgList) {
                CircuitPackageBean newCircuitGroup = new CircuitPackageBean();
                newCircuitGroup.putAll(cp.clone());
                newCircuitGroup.put(cg.getCircuitGroupKey(),cg.clone());
                newCircuitGroupList.add(newCircuitGroup);
            }
        }
        return newCircuitGroupList;
    }



    /**
     * 根据 {@link com.ehotting.edsta.circuitDesign.enums.SignalTypeEnum#getCode()}组合电路包
     * 如果signalType相同，转多组电路方案；
     * 不相同，转为同一组电路方案；
     *
     * @param circuitPackageList
     * @param circuitGroup
     */
    private void fillCircuitPackage(List<CircuitPackageBean> circuitPackageList,CircuitGroupBean circuitGroup){
        CircuitPackageBean newCircuitPackage = null;
        String key = circuitGroup.getCircuitGroupKey();
        logger.info("groupKey:{}",key);
        if(circuitPackageList.size()==0){
            newCircuitPackage = new CircuitPackageBean();
            newCircuitPackage.put(key,circuitGroup);
            circuitPackageList.add(newCircuitPackage);
            return ;
        }
        List<CircuitPackageBean> tempCircuitPackageList = new ArrayList<>();

        for(int i=0;i<circuitPackageList.size();i++){
            CircuitPackageBean circuitPackage = circuitPackageList.get(i);
            Set<String> signalTypeList = circuitPackage.keySet();
            if(signalTypeList.contains(key)){
                newCircuitPackage = new  CircuitPackageBean();
                newCircuitPackage.putAll(circuitPackage);
                circuitPackage.put(key,circuitGroup);
                tempCircuitPackageList.add(newCircuitPackage);
            }else{
                circuitPackage.put(key,circuitGroup);
            }
        }
 //       circuitPackageList.clear();
        circuitPackageList.addAll(tempCircuitPackageList);



    }



}